package cn.wolfcode.wolf2w.redis.service.impl;

import cn.wolfcode.wolf2w.domain.Strategy;
import cn.wolfcode.wolf2w.domain.UserFavor;
import cn.wolfcode.wolf2w.domain.UserInfo;
import cn.wolfcode.wolf2w.redis.service.IStatisVORedisService;
import cn.wolfcode.wolf2w.redis.util.RedisKeys;
import cn.wolfcode.wolf2w.service.IStrategyService;
import cn.wolfcode.wolf2w.util.DateUtil;
import cn.wolfcode.wolf2w.vo.StrategyStatisVo;
import com.alibaba.fastjson.JSON;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Service
public class StatisVORedisServiceImpl implements IStatisVORedisService {

    @Autowired
    private IStrategyService strategyService;

    @Autowired
    private StringRedisTemplate template;


    @Override
    public StrategyStatisVo getStrategyStatisVoById(String sid) {

        StrategyStatisVo vo = null;
        // 通过攻略id, 拿到当前访问的攻略
        Strategy strategy = strategyService.get(sid);
        // 通过攻略的id 拼接自定义攻略vo的key
        String key = RedisKeys.STRATEGY_STATIS_VO.join(sid);
        // 判断缓存中是否存在该key
        // 不存在
        if (!template.hasKey(key)){
            // 创建攻略vo对象
            vo = new StrategyStatisVo();
            // 复制攻略中的(xxxNum...)统计数据到vo中, vo中的字段与攻略对象的字段一致
            BeanUtils.copyProperties(strategy, vo);
            // 手动把攻略id 设置到 攻略vo中
            vo.setStrategyId(sid);
            // 把key缓存到redis中
            template.opsForValue().set(key, JSON.toJSONString(vo));
        } else {
        // 如果存在key, 获取出来, 因为是一个json字符串(set的时候设置为json字符串)了, 通过JSON.parseObject转成vo对象
            String voStr = template.opsForValue().get(key);
            vo = JSON.parseObject(voStr, StrategyStatisVo.class);
        }
        // 返回(原始数据封装好)的vo出去
        return vo;
    }

    @Override
    public void setStrategyStatisVo(StrategyStatisVo vo) {

        /**
         * 攻略vo 中 有StrategyId, 并且留意, 需要先操作getStrategyStatisVoById,
         * vo中的StrategyId 才会有值
         */
        String key = RedisKeys.STRATEGY_STATIS_VO.join(vo.getStrategyId());

        // 拿到更新后的vo 更新key中value
        template.opsForValue().set(key, JSON.toJSONString(vo));
    }

    @Override
    public void viewNumIncrease(String sid) {
        //StatisVo vo = null;
        //Strategy strategy = strategyService.get(sid);
        //String key = RedisKeys.STRATEGY_STATIS_VO.join(sid);
        //if (!template.hasKey(key)){
        //    vo = new StatisVo();
        //    BeanUtils.copyProperties(strategy, vo);
        //    vo.setStrategyId(sid);
        //
        //} else {
        //    String voStr = template.opsForValue().get(key);
        //    vo = JSON.parseObject(voStr, StatisVo.class);
        //}
        // 通过攻略id, 拿到vo(里面已经做了初始化或者已经拿到存在的)
        StrategyStatisVo vo = getStrategyStatisVoById(sid);
        vo.setViewnum(vo.getViewnum() + 1);
        // 更新redis缓存中的value --- vo
        setStrategyStatisVo(vo);
    }

    @Override
    public boolean favorNumIncrease(String sid, UserInfo userInfo) {
        // 拼接key 使用用户id 拼接 出key
        String key = RedisKeys.USER_FAVOR_STRATEGY.join(userInfo.getId());
        // 因为value是"多"个, 所以返回一个List 一个用户多个攻略id
        // 先初始化好这个List为null
        List<String> strategyIds = new ArrayList<>();
        // 拿到统计数据对象 vo
        StrategyStatisVo vo = this.getStrategyStatisVoById(sid);
        // 从redis中判断是否有这个key
        // 如果有 拿出所以的攻略id 封装到list中
        if(template.hasKey(key)) {
            String strList = template.opsForValue().get(key);
            // 通过JSON 拿到list集合
            strategyIds = JSON.parseArray(strList, String.class);
        }
        // 初始化为[],空集合
        if (strategyIds.contains(sid)){
            // 移出攻略id
            strategyIds.remove(sid);
            // vo 中的 favorNum - 1
            vo.setFavornum(vo.getFavornum() - 1);
        } else {
            // 添加攻略id
            strategyIds.add(sid);
            // vo 中的 favorNum + 1
            vo.setFavornum(vo.getFavornum() + 1);
        }
        // 更新 key
        template.opsForValue().set(key, JSON.toJSONString(strategyIds));
        // 更新 vo 中的统计数据
        this.setStrategyStatisVo(vo);
        return strategyIds.contains(sid);
    }

    @Override
    public List<String> isExistFavorStrategy(String sid, String uid) {
        // 通过拼接 uid ,拿到缓存中的攻略收藏key
        String key = RedisKeys.USER_FAVOR_STRATEGY.join(uid);
        List<String> sids = new ArrayList<>();
        // 判断该key 是否存在 redis中
        if(template.hasKey(key)) {
            // 如果存在
            // 从redis缓存 拿出value -- 攻略id的集合
            sids = JSON.parseArray(template.opsForValue().get(key), String.class);
        }
        // 不存在 什么都不做就好
        return sids;
    }

    @Override
    public boolean isThumbupToday(String sid, UserInfo userInfo) {
        // 拼接key
        String key = RedisKeys.USER_THUMBUP_STRATEGY.join(sid, userInfo.getId());
        // 判断key是否已经存在
        if(!template.hasKey(key)) {
            // 不存在
            // 拿到当前时间 与明天0分0s的时间差
            Date now = new Date();
            Long time = DateUtil.getDateBetween(now , DateUtil.getEndDate(now));
            // 将该key缓存到redis中 并设置key的有效性
            template.opsForValue().set(key, "1", time, TimeUnit.SECONDS);
            // 更新VO中的thumbupNum
            StrategyStatisVo vo = this.getStrategyStatisVoById(sid);
            vo.setThumbsupnum(vo.getThumbsupnum() + 1);
            this.setStrategyStatisVo(vo);
            return true;
        }
        return false;
    }

    @Override
    public List<StrategyStatisVo> getAllStrategyStatisVo() {
        List<StrategyStatisVo> vos = new ArrayList<>();
        // 拿到所有攻略统计数据的vo的key
        Set<String> keys = template.keys(RedisKeys.STRATEGY_STATIS_VO.join("*"));
        // 遍历所有key
        for (String key : keys) {
            String voStr = template.opsForValue().get(key);
            // 转化成vo
            StrategyStatisVo vo = JSON.parseObject(voStr, StrategyStatisVo.class);
            // 将所有vo对象添加到vos的列表中
            vos.add(vo);
        }
        return vos;
    }

    @Override
    public void replyNumIncrease(String sid) {
        StrategyStatisVo vo = getStrategyStatisVoById(sid);
        vo.setReplynum(vo.getReplynum() + 1);
        // 更新redis缓存中的value --- vo
        setStrategyStatisVo(vo);
    }

    @Override
    public List<UserFavor> getAllRedisUserFavor() {

        List<UserFavor> userFavors = new ArrayList<>();
        // 查询所有用户收藏攻略的key
        Set<String> keys = template.keys(RedisKeys.USER_FAVOR_STRATEGY.join("*"));
        // 遍历每一个key
        for (String key : keys) {
            // 创建用户收藏攻略对象
            UserFavor userFavor = new UserFavor();
            // 设置用户的Id
            userFavor.setUserId(key.replaceAll(RedisKeys.USER_FAVOR_STRATEGY.join(""), ""));
            // 获取当前用户所有收藏攻略的id
            String sids = template.opsForValue().get(key);
            // 设置所有收藏攻略的id到用户收藏对象中
            userFavor.setStrategyIds(JSON.parseArray(sids, String.class));
            // 将用户添加到集合中
            userFavors.add(userFavor);
        }
        return userFavors;
    }
}
